#pragma once
#include "Socket.hpp"
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
#include <functional>
using namespace SocketModule;
const static std::string sep = "/r/n"; // 分隔符
// client -> server
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }

    // 对象->字符串
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    // 字符串->对象
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }
    ~Request() {}

private:
    int _x;
    int _y;
    char _oper; // + - * / % -> _x _oper _y -> 10 + 20
};

// server -> client
class Response
{
public:
    Response() {}
    Response(int result, int code) : _result(result), _code(code)
    {
    }
    // 对象->字符串
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        return writer.write(root);
    }

    // 字符串->对象
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }

private:
    int _result; // 运算结果，无法区分清楚应答是计算结果，还是异常值
    int _code;   // 0:sucess, 1,2,3,4->不同的运算异常的情况, 约定！！！！
};

// 协议(基于TCP的)需要解决两个问题：
// 1. request和response必须得有序列化和反序列化功能
// 2. 你必须保证，读取的时候，读到完整的请求(TCP, UDP不用考虑)
class Protocol
{
public:
    using func_t = std::function<Response &(Request &req)>; // 定义协议层返回任务类型

private:
    // 封装报头
    // 长度 + 分隔符 + {} + 分隔符
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
    std::string Encode(const std::string &jsonstr)
    {
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    // 解析有效报文
    /// 50\r\n{"x" : 10, "y" : 20, "oper" : '+'}\r\n
    // 5
    // 50
    // 50\r
    // 50\r\n
    // 50\r\n{"x": 10, "
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n
    // 50\r\n{"x": 10, "y" : 20, "oper" : '+'}\r\n50\r\n{"x": 10, "y" : 20, "ope
    //.....
    bool Decode(std::string &buffer, std::string *package)
    {
        ssize_t first_sep_pos = buffer.find(sep, 0);
        if (first_sep_pos == std::string::npos)
        {
            return false;
        }

        // 可以获得理论有效报文长度 以及 有效长度的位数!
        std::string package_len_str = buffer.substr(0, first_sep_pos); // 有效长度
        ssize_t package_len_int = std::stoi(package_len_str);

        // 判断理论(目标)报文长度 和 实际报文长度是否相符
        // int target_len = buffer.find(sep, first_sep_pos + sep.size()) - first_sep_pos + sep.size(); // // 如果只是匹配有效报文长度则还要增加第二个分隔符未找到的判断
        int target_len = package_len_str.size() + 2 * sep.size() + package_len_int; // 实际报文长度
        if (buffer.size() < target_len)
        {
            return false;
        }

        // 至少有一个完整的报文
        // 报文分割
        *package = buffer.substr(first_sep_pos + sep.size(), package_len_int);
        buffer.erase(0, target_len);
        return true;
    }

public:
    Protocol(func_t func)
        : _func(func)
    {
    }

    bool GetRequest(std::shared_ptr<Socket> sock, InetAddr &client)
    {
        std::string buffer_queue;
        while (true)
        {
            // 1. 读取请求
            int n = sock->Read(buffer_queue);
            if (n > 0) // 正常连接
            {
                // 2. 判断是否存在有效报文
                std::string json_packet;
                bool ok = Decode(buffer_queue, &json_packet);
                if (!ok)
                {
                    continue;
                }

                // 3. 请求反序列化递交任务给上层
                Request req;
                req.Deserialize(json_packet); // 反序列化
                Response res = _func(req);    // 递交任务

                // 4. 获得响应 序列化
                res.Serialize();

                // 5. 添加报头
                std::string response_data = res.Serialize();
                Encode(response_data);

                // 6. 发送响应
                sock->Send(response_data);
            }

            else if (n == 0) // 对方正常关闭连接
            {
                LOG(LogLevel::INFO) << "client:" << client.StringAddr() << "Quit!";
                break;
            }

            else // 连接异常终止
            {
                LOG(LogLevel::WARNING) << "client:" << client.StringAddr() << ", recv error";
                break;
            }
        }
    }

    void BulidingRequest(std::string &client_request)
    {
        //
    }

private:
    func_t _func;
};